#!/bin/bash

# cjgit - Clone Command
# Clone all Cangjie projects (dev branch)

# Source common functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/cjgit-common.sh"

# Function to set up Git credentials automatically for a specific repository
setup_git_credentials() {
    local repo_dir="$1"
    local username="$2"
    local token="$3"
    local token_stored="$4"
    
    if [[ ! -d "$repo_dir" ]]; then
        print_error "Repository directory not found: $repo_dir"
        return 1
    fi
    
    if [[ -n "$username" && "$token_stored" == "true" ]]; then
        # Use pass-git-helper for token stored in pass
        if command -v pass-git-helper >/dev/null 2>&1; then
            # Configure Git to use pass-git-helper for this repository only
            local pass_git_helper_path=$(command -v pass-git-helper)
            git -C "$repo_dir" config credential.helper "$pass_git_helper_path"
        else
            print_error "pass-git-helper not found, please install it: https://github.com/languitar/pass-git-helper"
            return 1
        fi
    elif [[ -n "$username" && -n "$token" ]]; then
        # Add credentials to global file if they don't exist
        if ! grep -q "gitcode.com" "$HOME/.git-credentials" 2>/dev/null; then
            echo "https://$username:$token@gitcode.com" >> "$HOME/.git-credentials"
            chmod 600 "$HOME/.git-credentials"
        fi
        
        # Configure Git to use credential helper for this repository only
        git -C "$repo_dir" config credential.helper store
    fi
}

# Clone command implementation
clone_command() {
    local fork_user=""
    local upstream_only=false
    
    # Parse command line options
    while [[ $# -gt 0 ]]; do
        case $1 in
            --upstream-only)
                upstream_only=true
                shift
                ;;
            *)
                print_error "Unknown option: $1"
                echo
                help_command
                exit 1
                ;;
        esac
    done
    
    print_info "Starting clone operation for all Cangjie projects..."
    print_info "Cloning 'dev' branch by default"
    
    # Always use config unless upstream-only specified
    local existing_forks=()
    if [[ "$upstream_only" == false ]]; then
        if read_gitcode_config && [[ -n "$GITCODE_USER" && -n "$TOKEN" ]]; then
            fork_user="$GITCODE_USER"
            print_info "Using GitCode username from config: $fork_user"
            
            # Set up Git credentials automatically (will be done per-repo after cloning)
            
            print_info "Checking existing fork repositories..."
            existing_forks=($(get_fork_repositories "$fork_user" "$TOKEN"))
            echo
        else
            print_warning "Cannot read GitCode config, using upstream-only mode"
            echo ""
            echo "Please create the config file at $HOME/.config/cjpr.conf with the following format:"
            echo "GITCODE_USER=username"
            echo "TOKEN=token-id"
            echo ""
        fi
    fi
    echo
    
    for project in "${PROJECTS[@]}"; do
        # Check if project directory already exists
        if [[ -d "$project" ]]; then
            echo -e "${GRAY}✓${NC} $project ${GRAY}(already exists)${NC}"
            
            # Set up Git credentials for existing repository
            if read_gitcode_config && [[ -n "$GITCODE_USER" ]]; then
                setup_git_credentials "$project" "$GITCODE_USER" "$TOKEN" "$TOKEN_STORED"
            fi
            
            continue
        fi
        
        # Clone the repository with dev branch
        local upstream_url="$UPSTREAM_BASE/$project.git"
        
        if git clone -b dev "$upstream_url" "$project" 2>/dev/null; then
            # Change remote name to upstream if it's origin
            if [[ -d "$project" ]]; then
                if git -C "$project" remote get-url origin >/dev/null 2>&1; then
                    if git -C "$project" remote get-url origin | grep -q "Cangjie"; then
                        git -C "$project" remote rename origin upstream >/dev/null 2>&1
                    fi
                fi
                
                # Verify we're on the dev branch
                current_branch=$(git -C "$project" branch --show-current)
                if [[ "$current_branch" != "dev" ]]; then
                    git -C "$project" checkout dev >/dev/null 2>&1
                fi
                

                
                # Add fork remote if username is specified
                if [[ -n "$fork_user" ]]; then
                    # Create fork if it doesn't exist
                    if [[ ${#existing_forks[@]} -gt 0 ]]; then
                        create_fork_if_not_exists "$project" "${existing_forks[@]}"
                    fi
                    
                    local fork_url="https://gitcode.com/$fork_user/$project.git"
                    
                    if git -C "$project" remote add myfork "$fork_url" >/dev/null 2>&1; then
                        # Fetch from fork
                        git -C "$project" fetch myfork >/dev/null 2>&1
                    fi
                    
                    # Set up Git credentials for newly cloned repository
                    if read_gitcode_config && [[ -n "$GITCODE_USER" ]]; then
                        setup_git_credentials "$project" "$GITCODE_USER" "$TOKEN" "$TOKEN_STORED"
                    fi
                fi
            fi
            
            # Build the output line (after all operations including fork creation)
            local output_line="${GREEN}✓${NC} $upstream_url"
            
            # Add fork remote badge if username is specified
            if [[ -n "$fork_user" ]]; then
                output_line="$output_line ${GRAY}+ fork remote${NC}"
            fi
            
            echo -e "$output_line"
        else
            echo -e "${RED}✗${NC} $upstream_url ${RED}(failed)${NC}"
            print_error "Failed to clone $project dev branch from $upstream_url"
            print_error "This might happen if the dev branch doesn't exist in the repository"
            exit 1
        fi
    done
    
    print_success "Clone operation completed for all projects"
}

# Help function for clone command
help_command() {
    echo "Usage: cjgit clone [OPTIONS]"
    echo
    echo "Clone all Cangjie projects (dev branch)"
    echo
    echo "Options:"
    echo "  --upstream-only    Force upstream-only clone (ignore config)"
    echo
    echo "Examples:"
    echo "  cjgit clone                  # Clone all projects (dev branch) with fork remote from config"
    echo "  cjgit clone --upstream-only  # Force upstream-only clone (ignore config)"
}

# Function to get fork repositories from GitCode API
get_fork_repositories() {
    local username="$1"
    local token="$2"
    
    if [[ -z "$username" || -z "$token" ]]; then
        print_error "Username and token are required for API call"
        return 1
    fi
    
    local api_url="https://api.gitcode.com/api/v5/orgs/$username/repos?access_token=$token"
    
    print_info "Fetching repositories from GitCode API for user: $username"
    
    # Make API call and process the response
    local response
    response=$(curl -s -L "$api_url" -H 'Accept: application/json' 2>/dev/null)
    
    if [[ $? -ne 0 ]]; then
        print_error "Failed to fetch data from GitCode API"
        return 1
    fi
    
    # Check if response is valid JSON and contains data
    if ! echo "$response" | jq -e '. | length > 0' >/dev/null 2>&1; then
        print_error "Invalid response from GitCode API or no repositories found"
        return 1
    fi
    
    # Filter repositories where fork is true and extract names
    local fork_repos
    fork_repos=$(echo "$response" | jq -r '.[] | select(.fork == true) | .name' 2>/dev/null)
    
    if [[ $? -ne 0 ]]; then
        print_error "Failed to parse API response"
        return 1
    fi
    
    # Convert to array
    local repo_array=()
    while IFS= read -r repo; do
        if [[ -n "$repo" ]]; then
            repo_array+=("$repo")
        fi
    done <<< "$fork_repos"
    
    # Print the fork repositories found
    if [[ ${#repo_array[@]} -eq 0 ]]; then
        print_warning "No fork repositories found for user: $username"
    else
        print_success "Found ${#repo_array[@]} fork repositories:"
        for repo in "${repo_array[@]}"; do
            echo "  - $repo"
        done
    fi
    
    # Return the array (will be captured by caller)
    printf '%s\n' "${repo_array[@]}"
}

# Function to create a fork if it doesn't exist
create_fork_if_not_exists() {
    local repo_name="$1"
    local existing_forks=("${@:2}")
    local username="$GITCODE_USER"
    local token="$TOKEN"
    
    if [[ -z "$repo_name" || -z "$username" || -z "$token" ]]; then
        print_error "Repository name, username, and token are required"
        return 1
    fi
    
    # Check if fork already exists
    for existing_fork in "${existing_forks[@]}"; do
        if [[ "$existing_fork" == "$repo_name" ]]; then
            # Fork already exists, do nothing and don't print anything
            return 0
        fi
    done
    
    # Fork doesn't exist, create it
    print_info "Creating fork for repository: $repo_name"
    
    local api_url="https://api.gitcode.com/api/v5/repos/Cangjie/$repo_name/forks?access_token=$token"
    
    # Create JSON data using jq for proper formatting
    local json_data
    json_data=$(jq -n --arg org "$username" --arg name "$repo_name" --arg path "$repo_name" '
    {
        "organization": $org,
        "name": $name,
        "path": $path
    }' 2>/dev/null)
    
    if [[ $? -ne 0 || -z "$json_data" ]]; then
        print_error "Failed to create JSON data for fork creation"
        return 1
    fi
    
    # Make API call to create fork
    local response
    response=$(curl -s -L "$api_url" \
        -H 'Content-Type: application/json' \
        -H 'Accept: application/json' \
        -d "$json_data" 2>/dev/null)
    
    if [[ $? -ne 0 ]]; then
        print_error "Failed to create fork for $repo_name"
        return 1
    fi
    
    # Check if the request was successful
    if echo "$response" | jq -e '.id' >/dev/null 2>&1; then
        print_success "Successfully created fork for $repo_name"
        return 0
    else
        # Try to extract error message from response
        local error_message
        error_message=$(echo "$response" | jq -r '.error_message // .message // "Unknown error"' 2>/dev/null)
        
        if [[ $? -eq 0 && -n "$error_message" ]]; then
            print_error "Failed to create fork: $error_message"
        else
            print_error "Failed to create fork: Unknown error"
        fi
        
        # Abort immediately
        exit 1
    fi
}

# Main execution
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
    help_command
    exit 0
fi

clone_command "$@"